﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DnPakExplorer {
	public class Skill : IEnumerable<SkillEffect>{
		private int mRow;
		private Dntable mTable;
		private int mLevelRow;			// -2表示为加成技能等级信息，-1表示找不到技能等级信息
		private Dntable mLevelTable;
		private int mSkillLevel;

		public Skill(int row, Dntable table) {
			mRow = row;
			mTable = table;
			Level = 1;
		}

		public Dntable FromTable {
			get { return mTable; }
		}

		public int Row {
			get { return mRow; }
		}

		public int SkillID {
			get { return mTable.GetKey(mRow); }
		}

		public string Name {
			get {
				string name = Util.FindUIString((int)mTable[mRow, 0]);
				if (name == null)
					return "";
				return name;
			}
		}

		public int NeedJob {
			get { return (int)mTable[mRow, 5]; }
		}

		public int MaxLevel {
			get { return (int)mTable[mRow, 8]; }
		}

		public int IconId {
			get { return (int)mTable[mRow, 2]; }
		}

		public int BuffIconId {
			get { return (int)mTable[mRow, 3]; }
		}

		public int DebuffIconId {
			get { return (int)mTable[mRow, 4]; }
		}

		public int NeedWeaponType1 {
			get { return (int)mTable[mRow, 6]; }
		}

		public int NeedWeaponType2 {
			get { return (int)mTable[mRow, 7]; }
		}

		public int SkillType {
			get { return (int)mTable[mRow, 9]; }
		}

		public string SkillDescrition {
			get {
				if (SkillLevelRow<0) {
					return "未能找到技能等级数据。";
				} else {
					return Util.ParseDnString((int)SkillLevelTable[SkillLevelRow, 19], (string)SkillLevelTable[mLevelRow, 20]);
				}
			}
		}

		public int Level {
			get { return mSkillLevel; }
			set {
				if (mSkillLevel != value) {
					mLevelRow = -2;
				}
				mSkillLevel = value;
			}
		}

		protected Dntable SkillLevelTable {
			get {
				if (mLevelTable == null && mLevelRow == -2) {
					LoadLevelInfo();
				}
				return mLevelTable;
			}
		}

		protected int SkillLevelRow {
			get {
				if (mLevelRow == -2) {
					LoadLevelInfo();
				}
				return mLevelRow;
			}
		}

		private void LoadLevelInfo() {
			int skillId = SkillID;
			if (mLevelTable != null) {
				for (int r=0; r<mLevelTable.RecordCount; r++) {
					if ((int)mLevelTable[r, 0] == skillId && (int)mLevelTable[r, 1] == Level) {
						mLevelRow = r;
						return;
					}
				}
			} else {
				foreach (Dntable table in DnResourceUtil.SkillLevelTables) {
					for (int r=0; r<table.RecordCount; r++) {
						if ((int)table[r, 0] == skillId && (int)table[r, 1] == Level) {
							mLevelRow = r;
							mLevelTable = table;
							return;
						}
					}
				}
				mLevelRow = -1;
			}
		}


		public IEnumerator<SkillEffect> GetEnumerator() {
			if (SkillLevelRow>=0) {
				for (int i=14; i<=22; i+=2) {
					if ((int)mTable[mRow, i] > 0) {
						SkillEffect effect = new SkillEffect();
						effect.EffectClass = (int)mTable[mRow, i];
						effect.EffectClassType = (int)mTable[mRow, i+1];
						effect.EffectClassValue = (string)mLevelTable[mLevelRow, i-12];
						effect.Duration = (int)mLevelTable[mLevelRow, i-11];
						yield return effect;
					} else {
						yield break;
					}
				}
				for (int i=43; i<=45; i+=2) {
					if ((int)mTable[mRow, i] > 0) {
						SkillEffect effect = new SkillEffect();
						effect.EffectClass = (int)mTable[mRow, i];
						effect.EffectClassType = (int)mTable[mRow, i+1];
						effect.EffectClassValue = (string)mLevelTable[mLevelRow, i+9];
						effect.Duration = (int)mLevelTable[mLevelRow, i+10];
						yield return effect;
					} else {
						yield break;
					}
				}
			}
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
			return GetEnumerator();
		}

		public override string ToString() {
			return Name+"(lv."+Level+")";
		}
	}

	public class SkillEffect {
		public int EffectClass;
		public int EffectClassType;
		public string EffectClassValue;
		public int Duration;

		private static int[] SkillEffectIdFlags;

		public const int Value		= 0;
		public const int Percent	= 1<<16;
		public const int Rate		= 2<<16;

		public const int MASK_SKILL_FLAG		= 3<<16;
		public const int MASK_SKILL_PROPERTY	= (1<<16)-1;

		static SkillEffect() {
			SkillEffectIdFlags = new int[400];
			for (int i=0; i<SkillEffectIdFlags.Length; i++) {
				SkillEffectIdFlags[i] = (int)PropertyID.ID_MAX;
			}
			SkillEffectIdFlags[(int)SkillEffectId.PhysicalAttack] = (int)PropertyID.PhysicalAttack;
			SkillEffectIdFlags[(int)SkillEffectId.PhysicalAttackPer		] = (int)PropertyID.PhysicalAttack | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.Defense				] = (int)PropertyID.PysicalDefense;
			SkillEffectIdFlags[(int)SkillEffectId.Unkown				] = (int)PropertyID.ID_MAX;
			SkillEffectIdFlags[(int)SkillEffectId.Strength				] = (int)PropertyID.Strength;
			SkillEffectIdFlags[(int)SkillEffectId.Agility				] = (int)PropertyID.Agility;
			SkillEffectIdFlags[(int)SkillEffectId.Intelligence			] = (int)PropertyID.Intelligence;
			SkillEffectIdFlags[(int)SkillEffectId.Stamina				] = (int)PropertyID.Stamina;
			SkillEffectIdFlags[(int)SkillEffectId.HP					] = (int)PropertyID.HP;
			SkillEffectIdFlags[(int)SkillEffectId.MP					] = (int)PropertyID.MP;
			SkillEffectIdFlags[(int)SkillEffectId.HP2					] = (int)PropertyID.HP;
			SkillEffectIdFlags[(int)SkillEffectId.HPRecoveryPer			] = (int)PropertyID.ID_MAX;
			SkillEffectIdFlags[(int)SkillEffectId.MPRecovery			] = (int)PropertyID.ID_MAX;
			SkillEffectIdFlags[(int)SkillEffectId.MagicAttack			] = (int)PropertyID.MagicAttack;
			SkillEffectIdFlags[(int)SkillEffectId.MagicAttackPer		] = (int)PropertyID.MagicAttack | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.FireAttack			] = (int)PropertyID.FireAttack;
			SkillEffectIdFlags[(int)SkillEffectId.WaterAttack			] = (int)PropertyID.WaterAttack;
			SkillEffectIdFlags[(int)SkillEffectId.LightAttack			] = (int)PropertyID.LightAttack;
			SkillEffectIdFlags[(int)SkillEffectId.DarkAttack			] = (int)PropertyID.DarkAttack;
			SkillEffectIdFlags[(int)SkillEffectId.DefenceRate			] = (int)PropertyID.DarkDefense | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.FireDefense			] = (int)PropertyID.FireDefense;
			SkillEffectIdFlags[(int)SkillEffectId.Damage				] = (int)PropertyID.FinalDamage | Rate;
			SkillEffectIdFlags[(int)SkillEffectId.MAXHPPer				] = (int)PropertyID.HP | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.MAXMPPer				] = (int)PropertyID.MP | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.MPRecoveryPer2		] = (int)PropertyID.ID_MAX;
			SkillEffectIdFlags[(int)SkillEffectId.SuperArmor			] = (int)PropertyID.ID_MAX;
			SkillEffectIdFlags[(int)SkillEffectId.ClearDebuff			] = (int)PropertyID.ID_MAX;
			SkillEffectIdFlags[(int)SkillEffectId.StrengthPer			] = (int)PropertyID.Strength | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.AgilityPer			] = (int)PropertyID.Agility | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.IntelligencePer		] = (int)PropertyID.Intelligence | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.StaminaPer			] = (int)PropertyID.Stamina | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.MagicDefense			] = (int)PropertyID.MagicDefense;
			SkillEffectIdFlags[(int)SkillEffectId.StiffPer				] = (int)PropertyID.Stiff | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.StiffResistancePer	] = (int)PropertyID.StiffResistance | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.CriticlePer			] = (int)PropertyID.Critical | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.StunResistancePer		] = (int)PropertyID.StunResistance | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.MpConsume				] = (int)PropertyID.ID_MAX;
			SkillEffectIdFlags[(int)SkillEffectId.PhysicalAttack2		] = (int)PropertyID.PhysicalAttack;
			SkillEffectIdFlags[(int)SkillEffectId.PhysicalAttackPer2	] = (int)PropertyID.PhysicalAttack | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.MagicAttack2			] = (int)PropertyID.MagicAttack;
			SkillEffectIdFlags[(int)SkillEffectId.MagicAttackPer2		] = (int)PropertyID.MagicAttack | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.StunPer				] = (int)PropertyID.Stun | Percent;
			SkillEffectIdFlags[(int)SkillEffectId.Critical				] = (int)PropertyID.Critical;
			SkillEffectIdFlags[(int)SkillEffectId.CriticalRate			] = (int)PropertyID.Critical | Rate;
			SkillEffectIdFlags[(int)SkillEffectId.Experience			] = (int)PropertyID.ID_MAX;
			SkillEffectIdFlags[(int)SkillEffectId.FinalSkillCd			] = (int)PropertyID.ID_MAX;
			SkillEffectIdFlags[(int)SkillEffectId.AllElementDefense		] = (int)PropertyID.ID_MAX;
			SkillEffectIdFlags[(int)SkillEffectId.FinalDamageRate		] = (int)PropertyID.FinalDamage | Rate;
		}

		public PropertyID GetTargetPropertyId() {
			return (PropertyID)(SkillEffectIdFlags[EffectClass] & MASK_SKILL_PROPERTY);
		}

		public int GetPropertyFlag() {
			return SkillEffectIdFlags[EffectClass] & MASK_SKILL_FLAG;
		}
	}

	public enum SkillEffectId : int {
		PhysicalAttack		= 1  ,//			0				+物理攻击力
		PhysicalAttackPer	= 2  ,//			1				+物理攻击力%
		Defense				= 3  ,//			0				+防御力
		Unkown				= 4  ,//
		Strength			= 5  ,//		0				+力量
		Agility				= 6  ,//		0				+敏捷
		Intelligence		= 7  ,//		0				+智慧
		Stamina				= 8  ,//		0				+体质
		HP					= 9  ,//		0				+HP
		MP					= 10 ,//		0				+MP
		HP2					= 15 ,//		0				+HP
		HPRecoveryPer		= 16 ,//		0				恢复HP%
		MPRecovery			= 17 ,//		0				恢复MP
		MagicAttack			= 28 ,//		0				+魔法攻击力
		MagicAttackPer		= 29 ,//		1				+魔法攻击力%
		FireAttack			= 32 ,//		0				+火攻击
		WaterAttack			= 33 ,//		0				+水攻击
		LightAttack			= 34 ,//		0				+光攻击
		DarkAttack			= 35 ,//		0				+暗攻击
		DefenceRate			= 31 ,//		0				+防御概率
		FireDefense			= 36 ,//		0				+火防御
		Damage				= 50 ,//		0				+造成的伤害%
		MAXHPPer			= 58 ,//		0				+最大HP%
		MAXMPPer			= 59 ,//		0				+最大MP%
		MPRecoveryPer2		= 59 ,//		0				+MP恢复(每2秒)
		SuperArmor			= 61 ,//		0				超级盔甲
		ClearDebuff			= 83 ,//		1				消除x个增益
		StrengthPer			= 87 ,//		2				+力量%
		AgilityPer			= 88 ,//		2				+敏捷%
		IntelligencePer		= 89 ,//		2				+智慧%
		StaminaPer			= 90 ,//		2				+体质%
		MagicDefense		= 93 ,//		0				+魔法防御力
		StiffPer			= 123,//			0				+硬直%
		StiffResistancePer	= 124,//			0				+硬直抵抗%
		CriticlePer			= 125,//			0				+致命一击%
		StunResistancePer	= 128,//			0				+眩晕抵抗%
		MpConsume			= 139,//			2				+MP消耗%

		PhysicalAttack2		= 200,//			0				+物理攻击力
		PhysicalAttackPer2	= 201,//			0				+物理攻击力%
		MagicAttack2		= 202,//			0				+魔法攻击力
		MagicAttackPer2		= 203,//			0				+魔法攻击力%

		StunPer				= 127,//			0				+眩晕%
		Critical			= 234,//			0				+致命一击
		CriticalRate		= 251,//			2				+致命一击概率%
		Experience			= 255,//			0				+消灭怪物、通关经验值%
		FinalSkillCd		= 269,//			0				+最终技能冷却时间
		AllElementDefense	= 306,//			0				+所有属性抗
		FinalDamageRate		= 389,//			4				+最终%（自身和队友）
	}
}
